package com.zoe.onelink.redis.util;

import io.lettuce.core.event.EventBus;
import io.lettuce.core.event.connection.ConnectionActivatedEvent;
import io.lettuce.core.event.connection.ConnectionDeactivatedEvent;
import io.lettuce.core.resource.ClientResources;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.util.CollectionUtils;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2022</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2022-08-19
 */
@Slf4j
@RequiredArgsConstructor
public class LettuceWatcherUtil implements SmartInitializingSingleton {

    private static final AtomicBoolean ACTIVE = new AtomicBoolean(false);
    private final ApplicationContext applicationContext;
    private final RedisProperties redisProperties;

    public static boolean isActive() {
        return LettuceWatcherUtil.ACTIVE.get();
    }

    @Override
    public void afterSingletonsInstantiated() {
        if (this.isRedisSentinelOrClusterMode()) {
            ACTIVE.set(true);
            return;
        }
        this.applicationContext.getBeanProvider(LettuceConnectionFactory.class)
                .ifAvailable(lettuceConnectionFactory -> {
                    // 如果项目启动期间Redis服务就不可用,则不会触发该事件
                    ClientResources clientResources = lettuceConnectionFactory.getClientResources();
                    if (clientResources == null) {
                        return;
                    }
                    clientResources.eventBus().get().subscribe(event -> {
                        // 双重检查锁
                        if (event instanceof ConnectionDeactivatedEvent || event instanceof ConnectionActivatedEvent) {
                            synchronized (LettuceWatcherUtil.class) {
                                boolean isActive = !(event instanceof ConnectionDeactivatedEvent);
                                log.debug("切换Redis状态,Active={}", isActive);
                                LettuceWatcherUtil.ACTIVE.set(isActive);
                            }
                        }
                    });
                });
    }

    /**
     * Redis是否是哨兵或集群模式
     */
    private boolean isRedisSentinelOrClusterMode() {
        RedisProperties.Sentinel sentinelProp = this.redisProperties.getSentinel();
        RedisProperties.Cluster clusterProp = this.redisProperties.getCluster();
        return (sentinelProp != null && !CollectionUtils.isEmpty(sentinelProp.getNodes()))
                || (clusterProp != null && !CollectionUtils.isEmpty(clusterProp.getNodes()));
    }
}
